package com.qianfeng.iot.driverattrbute.service.impl;

//
//                            _ooOoo_  
//                           o8888888o  
//                           88" . "88  
//                           (| -_- |)  
//                            O\ = /O  
//                        ____/`---'\____  
//                      .   ' \\| |// `.  
//                       / \\||| : |||// \  
//                     / _||||| -:- |||||- \  
//                       | | \\\ - /// | |  
//                     | \_| ''\---/'' | |  
//                      \ .-\__ `-` ___/-. /  
//                   ___`. .' /--.--\ `. . __  
//                ."" '< `.___\_<|>_/___.' >'"".  
//               | | : `- \`.;`\ _ /`;.`/ - ` : | |  
//                 \ \ `-. \_ __\ /__ _/ .-` / /  
//         ======`-.____`-.___\_____/___.-`____.-'======  
//                            `=---='  
//  
//         .............................................  
//                  佛祖镇楼                  BUG辟易  
//          佛曰:  
//                  写字楼里写字间，写字间里程序员；  
//                  程序人员写程序，又拿程序换酒钱。  
//                  酒醒只在网上坐，酒醉还来网下眠；  
//                  酒醉酒醒日复日，网上网下年复年。  
//                  但愿老死电脑间，不愿鞠躬老板前；  
//                  奔驰宝马贵者趣，公交自行程序员。  
//                  别人笑我忒疯癫，我笑自己命太贱；  
//  


import cn.hutool.core.lang.UUID;
import com.dc3.common.model.DriverAttribute;
import com.qianfeng.iot.driverattrbute.service.DriverAttrbuteService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.r2dbc.core.R2dbcEntityTemplate;
import org.springframework.data.relational.core.query.Criteria;
import org.springframework.data.relational.core.query.Query;
import org.springframework.data.relational.core.query.Update;
import org.springframework.data.relational.core.sql.SqlIdentifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import reactor.core.publisher.Mono;

import java.util.HashMap;
import java.util.Map;

/**
 * Created by Jackiechan on 2022/8/10 20:45
 *
 * @author Jackiechan
 * @version 1.0
 * @since 1.0
 */
@Service
@Transactional
public class DriverAttrbuteServiceImpl implements DriverAttrbuteService {


    private R2dbcEntityTemplate r2dbcEntityTemplate;

    @Autowired
    public void setR2dbcEntityTemplate(R2dbcEntityTemplate r2dbcEntityTemplate) {
        this.r2dbcEntityTemplate = r2dbcEntityTemplate;
    }

    @Override
    public Mono<DriverAttribute> addAttrbute(DriverAttribute driverAttribute) {
        return findByNameAndDriverId(driverAttribute.getName(), driverAttribute.getDriverId())//先查询下数据
                //如果有数据
                .defaultIfEmpty(driverAttribute)
                //我们的业务要求数据不可以重复(同一个驱动的相同的名字),但是如果数据被删除了,然后再次添加的时候要以新添加的数据为准,相同的名字改成未删除并且其他数据和新添加的数据保持一致
                .flatMap(driverAttribute1 -> {
                    if (driverAttribute1.getId() != null) {

                        if (driverAttribute1.getDeleted() == 0) {
                            //数据存在并且没有删除,就抛出异常
                            throw new RuntimeException("数据已经存在");
                        }else{
                            //数据存在,但是被删除, 我们要更新为新的数据并且设置为未删除
                            driverAttribute.setDeleted(0);
                            driverAttribute.setId(driverAttribute1.getId());
                            return updateAttrbute(driverAttribute).map(integer -> driverAttribute);
                        }

                    }else{
                        //数据不存在
                        driverAttribute1.setId(UUID.randomUUID().toString(true));
                        driverAttribute1.setDeleted(0);
                        return r2dbcEntityTemplate.insert(DriverAttribute.class).into("dc3_driver_attribute").using(driverAttribute);
                    }

                });
    }


    @Override
    public Mono<Integer> updateAttrbute(DriverAttribute driverAttribute) {
        return r2dbcEntityTemplate.update(DriverAttribute.class)
                .inTable("dc3_driver_attribute")
                .matching(Query.query(Criteria.where("id").is(driverAttribute.getId())))
                .apply(getUpdate(driverAttribute));
    }


    @Override
    public Mono<DriverAttribute> findByNameAndDriverId(String name, String driverId) {
        return r2dbcEntityTemplate.select(DriverAttribute.class)
                .from("dc3_driver_attribute")
                .matching(Query.query(Criteria.where("name").is(name)
                        //这里我们没添加deleted条件,原因是因为上面的添加需要用到这个数据,添加需要知道是不是删除了,所以删除不能作为条件
                        .and(Criteria.where("driver_id").is(driverId)))).first();

    }

    @Override
    public Mono<DriverAttribute> findByNameId(String id) {
        return r2dbcEntityTemplate.select(DriverAttribute.class)
                .from("dc3_driver_attribute")
                .matching(Query.query(Criteria.where("id").is(id)
                        .and(Criteria.where("deleted").is(0)))).first();
    }


    /**
     * 创建一个更新的对象,主要是设置更新什么数据的
     * @param driverAttribute
     * @return
     */
    Update getUpdate(DriverAttribute driverAttribute) {
        Map<SqlIdentifier, Object> map = new HashMap<>();
        if (StringUtils.hasText(driverAttribute.getDisplayName())) {
            map.put(SqlIdentifier.quoted("display_name"), driverAttribute.getDisplayName());
        }
        if (StringUtils.hasText(driverAttribute.getName())) {
            map.put(SqlIdentifier.quoted("name"), driverAttribute.getName());
        }
        if (StringUtils.hasText(driverAttribute.getType())) {
            map.put(SqlIdentifier.quoted("type"), driverAttribute.getType());
        }
        if (StringUtils.hasText(driverAttribute.getValue())) {
            map.put(SqlIdentifier.quoted("value"), driverAttribute.getValue());
        }
        if (StringUtils.hasText(driverAttribute.getDescription())) {
            map.put(SqlIdentifier.quoted("description"), driverAttribute.getDescription());
        }
        if (!ObjectUtils.isEmpty(driverAttribute.getDeleted())) {
            map.put(SqlIdentifier.quoted("deleted"), driverAttribute.getDeleted());
        }

        return Update.from(map);
    }
}
